home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / email / Generator.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  10KB  |  303 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''Classes to generate plain text from a message object tree.'''
  5. import re
  6. import sys
  7. import time
  8. import random
  9. import warnings
  10. from cStringIO import StringIO
  11. from email.Header import Header
  12. UNDERSCORE = '_'
  13. NL = '\n'
  14. fcre = re.compile('^From ', re.MULTILINE)
  15.  
  16. def _is8bitstring(s):
  17.     if isinstance(s, str):
  18.         
  19.         try:
  20.             unicode(s, 'us-ascii')
  21.         except UnicodeError:
  22.             return True
  23.         except:
  24.             None<EXCEPTION MATCH>UnicodeError
  25.         
  26.  
  27.     None<EXCEPTION MATCH>UnicodeError
  28.     return False
  29.  
  30.  
  31. class Generator:
  32.     '''Generates output from a Message object tree.
  33.  
  34.     This basic generator writes the message to the given file object as plain
  35.     text.
  36.     '''
  37.     
  38.     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78):
  39.         """Create the generator for message flattening.
  40.  
  41.         outfp is the output file-like object for writing the message to.  It
  42.         must have a write() method.
  43.  
  44.         Optional mangle_from_ is a flag that, when True (the default), escapes
  45.         From_ lines in the body of the message by putting a `>' in front of
  46.         them.
  47.  
  48.         Optional maxheaderlen specifies the longest length for a non-continued
  49.         header.  When a header line is longer (in characters, with tabs
  50.         expanded to 8 spaces) than maxheaderlen, the header will split as
  51.         defined in the Header class.  Set maxheaderlen to zero to disable
  52.         header wrapping.  The default is 78, as recommended (but not required)
  53.         by RFC 2822.
  54.         """
  55.         self._fp = outfp
  56.         self._mangle_from_ = mangle_from_
  57.         self._maxheaderlen = maxheaderlen
  58.  
  59.     
  60.     def write(self, s):
  61.         self._fp.write(s)
  62.  
  63.     
  64.     def flatten(self, msg, unixfrom = False):
  65.         """Print the message object tree rooted at msg to the output file
  66.         specified when the Generator instance was created.
  67.  
  68.         unixfrom is a flag that forces the printing of a Unix From_ delimiter
  69.         before the first object in the message tree.  If the original message
  70.         has no From_ delimiter, a `standard' one is crafted.  By default, this
  71.         is False to inhibit the printing of any From_ delimiter.
  72.  
  73.         Note that for subobjects, no From_ line is printed.
  74.         """
  75.         if unixfrom:
  76.             ufrom = msg.get_unixfrom()
  77.             if not ufrom:
  78.                 ufrom = 'From nobody ' + time.ctime(time.time())
  79.             
  80.             print >>self._fp, ufrom
  81.         
  82.         self._write(msg)
  83.  
  84.     
  85.     def __call__(self, msg, unixfrom = False):
  86.         warnings.warn('__call__() deprecated; use flatten()', DeprecationWarning, 2)
  87.         self.flatten(msg, unixfrom)
  88.  
  89.     
  90.     def clone(self, fp):
  91.         '''Clone this generator with the exact same options.'''
  92.         return self.__class__(fp, self._mangle_from_, self._maxheaderlen)
  93.  
  94.     
  95.     def _write(self, msg):
  96.         oldfp = self._fp
  97.         
  98.         try:
  99.             self._fp = sfp = StringIO()
  100.             self._dispatch(msg)
  101.         finally:
  102.             self._fp = oldfp
  103.  
  104.         meth = getattr(msg, '_write_headers', None)
  105.         if meth is None:
  106.             self._write_headers(msg)
  107.         else:
  108.             meth(self)
  109.         self._fp.write(sfp.getvalue())
  110.  
  111.     
  112.     def _dispatch(self, msg):
  113.         main = msg.get_content_maintype()
  114.         sub = msg.get_content_subtype()
  115.         specific = UNDERSCORE.join((main, sub)).replace('-', '_')
  116.         meth = getattr(self, '_handle_' + specific, None)
  117.         if meth is None:
  118.             generic = main.replace('-', '_')
  119.             meth = getattr(self, '_handle_' + generic, None)
  120.             if meth is None:
  121.                 meth = self._writeBody
  122.             
  123.         
  124.         meth(msg)
  125.  
  126.     
  127.     def _write_headers(self, msg):
  128.         for h, v in msg.items():
  129.             print >>self._fp, '%s:' % h,
  130.             if self._maxheaderlen == 0:
  131.                 print >>self._fp, v
  132.                 continue
  133.             if isinstance(v, Header):
  134.                 print >>self._fp, v.encode()
  135.                 continue
  136.             if _is8bitstring(v):
  137.                 print >>self._fp, v
  138.                 continue
  139.             print >>self._fp, Header(v, maxlinelen = self._maxheaderlen, header_name = h, continuation_ws = '\t').encode()
  140.         
  141.         print >>self._fp
  142.  
  143.     
  144.     def _handle_text(self, msg):
  145.         payload = msg.get_payload()
  146.         if payload is None:
  147.             return None
  148.         
  149.         cset = msg.get_charset()
  150.         if cset is not None:
  151.             payload = cset.body_encode(payload)
  152.         
  153.         if not isinstance(payload, basestring):
  154.             raise TypeError('string payload expected: %s' % type(payload))
  155.         
  156.         if self._mangle_from_:
  157.             payload = fcre.sub('>From ', payload)
  158.         
  159.         self._fp.write(payload)
  160.  
  161.     _writeBody = _handle_text
  162.     
  163.     def _handle_multipart(self, msg):
  164.         msgtexts = []
  165.         subparts = msg.get_payload()
  166.         if subparts is None:
  167.             subparts = []
  168.         elif isinstance(subparts, basestring):
  169.             self._fp.write(subparts)
  170.             return None
  171.         elif not isinstance(subparts, list):
  172.             subparts = [
  173.                 subparts]
  174.         
  175.         for part in subparts:
  176.             s = StringIO()
  177.             g = self.clone(s)
  178.             g.flatten(part, unixfrom = False)
  179.             msgtexts.append(s.getvalue())
  180.         
  181.         alltext = NL.join(msgtexts)
  182.         boundary = msg.get_boundary(failobj = _make_boundary(alltext))
  183.         if msg.get_boundary() != boundary:
  184.             msg.set_boundary(boundary)
  185.         
  186.         if msg.preamble is not None:
  187.             print >>self._fp, msg.preamble
  188.         
  189.         print >>self._fp, '--' + boundary
  190.         if msgtexts:
  191.             self._fp.write(msgtexts.pop(0))
  192.         
  193.         for body_part in msgtexts:
  194.             print >>self._fp, '\n--' + boundary
  195.             self._fp.write(body_part)
  196.         
  197.         self._fp.write('\n--' + boundary + '--')
  198.         if msg.epilogue is not None:
  199.             print >>self._fp
  200.             self._fp.write(msg.epilogue)
  201.         
  202.  
  203.     
  204.     def _handle_message_delivery_status(self, msg):
  205.         blocks = []
  206.         for part in msg.get_payload():
  207.             s = StringIO()
  208.             g = self.clone(s)
  209.             g.flatten(part, unixfrom = False)
  210.             text = s.getvalue()
  211.             lines = text.split('\n')
  212.             if lines and lines[-1] == '':
  213.                 blocks.append(NL.join(lines[:-1]))
  214.                 continue
  215.             blocks.append(text)
  216.         
  217.         self._fp.write(NL.join(blocks))
  218.  
  219.     
  220.     def _handle_message(self, msg):
  221.         s = StringIO()
  222.         g = self.clone(s)
  223.         g.flatten(msg.get_payload(0), unixfrom = False)
  224.         self._fp.write(s.getvalue())
  225.  
  226.  
  227. _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
  228.  
  229. class DecodedGenerator(Generator):
  230.     '''Generator a text representation of a message.
  231.  
  232.     Like the Generator base class, except that non-text parts are substituted
  233.     with a format string representing the part.
  234.     '''
  235.     
  236.     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78, fmt = None):
  237.         """Like Generator.__init__() except that an additional optional
  238.         argument is allowed.
  239.  
  240.         Walks through all subparts of a message.  If the subpart is of main
  241.         type `text', then it prints the decoded payload of the subpart.
  242.  
  243.         Otherwise, fmt is a format string that is used instead of the message
  244.         payload.  fmt is expanded with the following keywords (in
  245.         %(keyword)s format):
  246.  
  247.         type       : Full MIME type of the non-text part
  248.         maintype   : Main MIME type of the non-text part
  249.         subtype    : Sub-MIME type of the non-text part
  250.         filename   : Filename of the non-text part
  251.         description: Description associated with the non-text part
  252.         encoding   : Content transfer encoding of the non-text part
  253.  
  254.         The default value for fmt is None, meaning
  255.  
  256.         [Non-text (%(type)s) part of message omitted, filename %(filename)s]
  257.         """
  258.         Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
  259.         if fmt is None:
  260.             self._fmt = _FMT
  261.         else:
  262.             self._fmt = fmt
  263.  
  264.     
  265.     def _dispatch(self, msg):
  266.         for part in msg.walk():
  267.             maintype = part.get_content_maintype()
  268.             if maintype == 'text':
  269.                 print >>self, part.get_payload(decode = True)
  270.                 continue
  271.             if maintype == 'multipart':
  272.                 continue
  273.             print >>self, self._fmt % {
  274.                 'type': part.get_content_type(),
  275.                 'maintype': part.get_content_maintype(),
  276.                 'subtype': part.get_content_subtype(),
  277.                 'filename': part.get_filename('[no filename]'),
  278.                 'description': part.get('Content-Description', '[no description]'),
  279.                 'encoding': part.get('Content-Transfer-Encoding', '[no encoding]') }
  280.         
  281.  
  282.  
  283. _width = len(repr(sys.maxint - 1))
  284. _fmt = '%%0%dd' % _width
  285.  
  286. def _make_boundary(text = None):
  287.     token = random.randrange(sys.maxint)
  288.     boundary = '=' * 15 + _fmt % token + '=='
  289.     if text is None:
  290.         return boundary
  291.     
  292.     b = boundary
  293.     counter = 0
  294.     while True:
  295.         cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
  296.         if not cre.search(text):
  297.             break
  298.         
  299.         b = boundary + '.' + str(counter)
  300.         counter += 1
  301.     return b
  302.  
  303.